import Layout from '@components/layout';
import Livere from '@components/livere';
import Markdown from '@components/markdown';
import * as WorkApi from '@lib/api/work';
import * as Stat from '@lib/stat';
import { ICategory, IHistory, IUser, IWork } from '@lib/types';
import { listAs, listHref, userAs, userHref } from '@lib/url';
import { getCategory, onCopy } from '@lib/utils';
import Voted from '@lib/voted';
import { Button, Card, Col, Dropdown, Icon, List, Menu, message, Modal, Popconfirm, Row, Tag } from 'antd';
import mediumZoom from 'medium-zoom';
import Link from 'next/link';
import Router from 'next/router';
import * as React from 'react';
import Clipboard from 'react-clipboard.js';
import { connect } from 'react-redux';
import './view.less';

interface IShare {
	name: string;
	url: string;
	tag: string;
}

interface IViewProps {
	id: number;
	category: ICategory[];
	work: IWork;
	author: IUser;
	history: IHistory[];
	user: IUser | null | undefined;
}

interface IViewState {
	category: ICategory[];
	history: IHistory[];
	work: IWork;
	author: IUser;
	share: IShare[];
	shouldDisplayMore: boolean[];
	modalShow: boolean;
	modalContent: string;
	voted?: boolean;
	videoShow: boolean;
	video: React.ReactNode | null;
}

class View extends React.Component<IViewProps, IViewState> {
	static async getInitialProps(param: any) {
		const res = await WorkApi.Get(param.query.id, false);
		if (res instanceof Error) {
			return {};
		}
		return {
			id: param.query.id,
			work: res.work,
			author: res.author,
			history: res.history.reverse()
		};
	}
	private last_id: number;
	constructor(props: any) {
		super(props);
		this.state = this.getStateFromProps(props);
		this.last_id = this.state.work.id;
		this.onVote = this.onVote.bind(this);
		this.onDelete = this.onDelete.bind(this);
	}
	private getStateFromProps(props: IViewProps) {
		const isWorkNotChange = this.last_id === props.work.id;
		const shouldDisplayMore = [];
		for (let i = 0; i < this.props.history.length; i++) {
			shouldDisplayMore.push(false);
		}
		return {
			category: props.category,
			work: props.work,
			author: props.author,
			history: props.history,
			share: isWorkNotChange ? this.state.share : [],
			shouldDisplayMore,
			modalShow: false,
			modalContent: "",
			voted: isWorkNotChange ? this.state.voted : undefined,
			videoShow: false,
			video: isWorkNotChange ? this.state.video : (() => {
				const it = props.work.video.split('|');
				switch (it[0]) {
					case 'bilibili':
						return (<iframe src={`https://player.bilibili.com/player.html?aid=${it[1]}`} allowFullScreen={true}></iframe>);
					case 'youku':
						return (<iframe src={`https://player.youku.com/embed/${it[1]}`} allowFullScreen={true}></iframe>);
					case 'qq':
						return (<iframe src={`https://v.qq.com/txp/iframe/player.html?vid=${it[1]}`} allowFullScreen={true}></iframe>);
					default:
						return null;
				}
			})()
		};
	}
	public componentWillReceiveProps(props: any) {
		this.setState(this.getStateFromProps(props));
	}
	public componentDidMount() {
		this.last_id = this.state.work.id;
		this.updateInterface();
	}
	public componentDidUpdate() {
		if (this.last_id !== this.state.work.id) {
			this.last_id = this.state.work.id;
			this.updateInterface();
		}
	}
	private updateInterface() {
		Stat.click(this.props.id);
		const shouldDisplayMore: boolean[] = [];
		document.querySelectorAll('.changelog .markdown-body').forEach(it => {
			shouldDisplayMore.push((it as HTMLElement).offsetHeight >= 400);
		});
		mediumZoom('.markdown-body img');
		this.setState({
			shouldDisplayMore,
			share: [
				['QQ空间', 'qzone', 'https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url={{URL}}&title={{TITLE}}'],
				['QQ', 'qq', 'https://connect.qq.com/widget/shareqq/index.html?url={{URL}}&title={{TITLE}}'],
				['微博', 'weibo', 'https://service.weibo.com/share/share.php?url={{URL}}&title={{TITLE}}']
			].map(it => {
				const url = it[2].replace('{{URL}}', encodeURIComponent(window.location.href))
					.replace('{{TITLE}}', encodeURIComponent(this.state.work.name));
				return {
					name: it[0],
					tag: it[1],
					url: url
				};
			}),
			voted: Voted.is(this.props.id.toString())
		});
	}
	public async onVote() {
		if (Voted.is(this.props.id.toString())) {
			return;
		}
		Stat.vote(this.props.id);
		Voted.add(this.props.id.toString());
		const res = Object.assign({}, this.state.work);
		res.vote++;
		this.setState({
			voted: true,
			work: res
		});
	}
	public async onDelete() {
		const res = await WorkApi.Del(this.props.id);
		if (!(res instanceof Error)) {
			message.success('删除成功');
			Router.back();
		}
	}
	public renderShare() {
		const res = this.state.share.map(it => {
			return (
				<Menu.Item key={it.tag} onClick={() => Stat.share(it.tag, this.props.id)}>
					<a target="_blank" href={it.url}>{it.name}</a>
				</Menu.Item>
			);
		});
		return (<Menu>{res}</Menu>);
	}
	public renderManage() {
		if (this.props.user && (this.props.user.is_admin == 1 || this.state.work.user_id === this.props.user.id)) {
			return (
				<Card title="管理" className="card-have-top">
					<Button.Group>
						<Button>
							<Link href={`/work/edit?id=${this.props.id}`}><a>编辑</a></Link>
						</Button>
						<Button>
							<Link href={`/work/upgrade?id=${this.props.id}`}><a>更新</a></Link>
						</Button>
						{this.props.user.is_admin == 1 ? (<Popconfirm
							title="您确认删除此作品吗？此操作不可撤销"
							onConfirm={this.onDelete}
							okText="删除"
							cancelText="取消"
						>
							<Button>删除</Button>
						</Popconfirm>) : ""}
					</Button.Group>
				</Card>
			);
		} else {
			return "";
		}
	}
	public renderAuthor() {
		const res = [];
		res.push(<Link href={userHref(this.state.author.id)} as={userAs(this.state.author.id)}><a><Icon type="user"></Icon></a></Link>);
		if (this.state.author.bilibili_id) {
			res.push(<a href={`https://space.bilibili.com/${this.state.author.bilibili_id}`} target="_blank" rel="nofollow"><i className="iconfont icon-bilibili"></i></a>);
		}
		if (this.state.author.nga_id) {
			res.push(<a href={`https://bbs.nga.cn/nuke.php?func=ucp&uid=${this.state.author.nga_id}`} target="_blank" rel="nofollow"><i className="iconfont icon-nga"></i></a>);
		}
		if (this.state.author.weibo_id) {
			res.push(<a href={`https://weibo.com/${this.state.author.weibo_id}`} target="_blank" rel="nofollow"><i className="iconfont icon-weibo"></i></a>);
		}
		return res;
	}
	public render() {
		const tags = this.state.work.tag.map(it => <Tag key={it}><Link href={`/search?text=${it}`}><a>{it}</a></Link></Tag>)
		return (
			<Layout title={this.state.work.name} className="page-work-view">
				<Row gutter={8}>
					<Col span={24} lg={18}>
						<Card title={this.state.work.name} extra={<span><Icon type="number" /> {this.props.id}</span>}>
							<div className="description">{this.state.work.description}</div>
							<div className="tags">
								<Tag key="video" onClick={() => this.setState({ videoShow: true })} style={{
									display: this.state.video === null ? "none" : "inline-block"
								}}><a><Icon type="caret-right" /> 播放介绍视频</a></Tag>
								{tags}
							</div>
							<Markdown text={this.state.work.detail || ""} className="detail markdown-body"></Markdown>
						</Card>
						<Card
							className="card-have-top"
							title="评论"
							extra={<small>测试中</small>}
						>
							<Livere id={this.props.id} uid="MTAyMC80NDQ0MC8yMDk3Mg=="></Livere>
						</Card>
					</Col>
					<Col span={24} lg={6} className="sidebar">
						<Card title="分享码" className="share-code">
							<Clipboard component="a" data-clipboard-text={this.state.work.code} onSuccess={() => onCopy("code", this.props.id)}>{this.state.work.code}</Clipboard>
						</Card>
						{this.renderManage()}
						<Card
							title="作品信息"
							actions={this.renderAuthor()}
							extra={typeof (this.state.voted) === "undefined" ? <Icon type="loading" /> : <Button icon="like" type="dashed" size="small" disabled={this.state.voted} onClick={this.onVote}>{this.state.work.vote}</Button>}
							className="card-have-top"
						>
							<p><Icon type="user" /> <Link href={userHref(this.state.author.id)} as={userAs(this.state.author.id)}><a>{this.state.author.name}</a></Link></p>
							<p><Icon type="appstore" /> <Link href={listHref(this.state.work.category_id, 1, "time")} as={listAs(this.state.work.category_id, 1, "time")}><a>{getCategory(this.props.category, this.state.work.category_id)}</a></Link></p>
							<p><Icon type="fire" /> {this.state.work.hot / 10} ℃</p>
							<p><Icon type="share-alt" /> <Dropdown overlay={this.renderShare()}>
								<a className="ant-dropdown-link" href="#">
									分享到 <Icon type="caret-down" />
								</a>
							</Dropdown></p>
							<p><Icon type="link" /> <Clipboard component="a" data-clipboard-text={`https://owmod.net/${this.props.id}`} onSuccess={() => onCopy("link", this.props.id)}>复制链接</Clipboard></p>
							<p><Icon type="history" /> {this.state.work.update_time}</p>
						</Card>
						<Card className="changelog card-have-top">
							<List
								itemLayout="horizontal"
								dataSource={this.state.history}
								renderItem={(item, index) => (
									<List.Item>
										<div className="item">
											<Markdown text={item.detail || ""} className="detail markdown-body"></Markdown>
											<div className="more" style={{
												display: this.state.shouldDisplayMore[index] ? "block" : "none"
											}}>
												<Button block onClick={() => this.setState({
													modalShow: true,
													modalContent: item.detail || ""
												})}>更多</Button>
											</div>
											<div className="action">
												<Clipboard component="a" data-clipboard-text={item.code} onSuccess={() => onCopy("code", this.props.id)}>{item.code}</Clipboard>
												<span style={{
													float: "right"
												}}>{item.update_time}</span>
											</div>
										</div>
									</List.Item>
								)}
							/>
						</Card>
					</Col>
				</Row>
				<Modal
					title="更新日志"
					visible={this.state.modalShow}
					onCancel={() => this.setState({ modalShow: false })}
					cancelText="关闭"
					okButtonProps={{ style: { display: "none" } }}
					className="changelog-modal"
					width="80%"
				>
					<Markdown text={this.state.modalContent} className="markdown-body"></Markdown>
				</Modal>
				<Modal
					title="介绍视频"
					visible={this.state.videoShow}
					onCancel={() => this.setState({ videoShow: false })}
					className="video-modal"
					width="850px"
				>
					{this.state.video}
				</Modal>
			</Layout>
		);
	}
}

const mapStateToProps = (state: any) => ({
	category: state.category,
	user: state.user
});

export default connect(mapStateToProps)(View);